package Modelo.ServicoEventos;

import java.io.File;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.List;

import javax.sql.DataSource;

import Modelo.Despesa.Despesa;
import Modelo.Despesa.DespesaDao;
import Modelo.DespesaApresentador.DespesaApresentador;
import Modelo.DespesaApresentador.DespesaApresentadorDao;
import Modelo.Edicao.Edicao;
import Modelo.Edicao.EdicaoDao;
import Modelo.Evento.Evento;
import Modelo.Evento.EventoDao;
import Modelo.Participante.Participante;
import Modelo.Participante.ParticipanteDao;
import Modelo.Patrocinador.Patrocinador;
import Modelo.Patrocinador.PatrocinadorDao;
import Modelo.Patrocinio.Patrocinio;
import Modelo.Patrocinio.PatrocinioDao;
import Modelo.Pessoa.Pessoa;
import Modelo.Pessoa.PessoaDao;
import Util.ExcecaoNaoApresentador;
import Util.ExcecaoValorPatrocinioDiminuido;
import Util.SQLUtil;
import Util.ExcecaoInstanciaNaoEncontrada;
import Util.ExcecaoSaldoInsuficiente;

public class ServicoEventos {
	private DataSource dataSource;
	private Connection connection;
	private DespesaDao despesaDao = null;
	private DespesaApresentadorDao despesaApresentadorDao = null;
	private EdicaoDao edicaoDao = null;
	private EventoDao eventoDao = null;
	private ParticipanteDao participanteDao = null;
	private PatrocinadorDao patrocinadorDao = null;
	private PatrocinioDao patrocinioDao = null;
	private PessoaDao pessoaDao = null;
	
	private static final String URL = "jdbc:mysql://localhost/Trabalho";
	private static final String USUARIO = "root";
	private static final String SENHA = "admin";
	
	public ServicoEventos() {
		super();
		//InetAddress addr = InetAddress.getByName("192.168.183.2");
		//URL = addr.getHostName() +
		try {
			 
			Class.forName("com.mysql.jdbc.Driver");
 
		} catch (ClassNotFoundException e) {
 
			System.out.println("Where is your MySQL JDBC Driver?");
			e.printStackTrace();
			return;
 
		}
		try {
			connection = DriverManager.getConnection(URL, USUARIO, SENHA);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			System.out.println("Erro de conexao ao DB");
			e.printStackTrace();
		}
		despesaDao = new DespesaDao();
		despesaApresentadorDao = new DespesaApresentadorDao();
		edicaoDao = new EdicaoDao();
		eventoDao = new EventoDao();
		participanteDao = new ParticipanteDao();
		patrocinadorDao = new PatrocinadorDao();
		pessoaDao = new PessoaDao();
		patrocinioDao = new PatrocinioDao();
		SQLUtil.executeSqlScript(connection, new File(System.getProperty("user.dir") +
				"\\src\\Modelo\\ServicoEventos\\Resources\\create_tables.sql"));
	}
	
	public Despesa adicionaDespesa(Despesa despesa) throws ExcecaoSaldoInsuficiente{
		Despesa retDespesa = null;
		try{
			Patrocinio patrocinio = patrocinioDao.buscarPatrocinio(connection, 
					despesa.getCnpjPatrocinador(), despesa.getCodEvento(), Long.valueOf(despesa.getNroEdicao()));
			float novoSaldo = patrocinio.getSaldoPatrocinio() - despesa.getValorDespesa();
			if(novoSaldo < 0){
				throw new ExcecaoSaldoInsuficiente(patrocinio.getCnpjPatrocinador(), 
						despesa.getCodEvento(), despesa.getNroEdicao(), despesa.getCodDespesa());
			}
			patrocinio.setSaldoPatrocinio(novoSaldo);
			patrocinioDao.updatePatrocinio(connection, patrocinio);
			retDespesa = despesaDao.adicionarDespesa(connection, despesa);
		} catch (ExcecaoInstanciaNaoEncontrada e){
			e.printStackTrace();
		}
		
		return retDespesa;
	}
	
	public void removeDespesa (long codDespesa, long codEvento, int nroEdicao) throws ExcecaoInstanciaNaoEncontrada{
		try {
			Despesa despesa = despesaDao.buscarDespesa(connection, codEvento, nroEdicao, codDespesa);
			Patrocinio patrocinio = patrocinioDao.buscarPatrocinio(connection, 
					despesa.getCnpjPatrocinador(), codEvento, Long.valueOf(nroEdicao));
			
			float novoSaldo = patrocinio.getSaldoPatrocinio() + despesa.getValorDespesa();
			patrocinio.setSaldoPatrocinio(novoSaldo);
			patrocinioDao.updatePatrocinio(connection, patrocinio);
			despesaDao.removerDespesa(connection, codEvento, nroEdicao, codDespesa);
		} catch (ExcecaoInstanciaNaoEncontrada e){
			e.printStackTrace();
		}
	}
	public void updateDespesa(Despesa despesa) throws ExcecaoInstanciaNaoEncontrada, ExcecaoSaldoInsuficiente{
		Despesa despesa0 = despesaDao.buscarDespesa(connection, 
				despesa.getCodEvento(), despesa.getNroEdicao(), despesa.getCodDespesa());
		if(despesa0.getValorDespesa() != despesa.getValorDespesa()){
			Patrocinio patrocinio = null;
			try {
				patrocinio = patrocinioDao.buscarPatrocinio(connection, 
						despesa.getCnpjPatrocinador(), despesa.getCodEvento(), Long.valueOf(despesa.getNroEdicao()));
			} catch (ExcecaoInstanciaNaoEncontrada e) {
				throw new ExcecaoInstanciaNaoEncontrada(new Long []{despesa.getCodEvento(), Long.valueOf(despesa
						.getNroEdicao()), despesa.getCodDespesa()}, "Despesa");
			}
			float novoSaldo = patrocinio.getSaldoPatrocinio() + despesa0.getValorDespesa() - despesa.getValorDespesa();
			patrocinio.setSaldoPatrocinio(novoSaldo);
			patrocinioDao.updatePatrocinio(connection, patrocinio);
		}
		despesaDao.updateDespesa(connection, despesa);
	}
	public Despesa buscaDespesa (long codDespesa, long codEvento, int nroEdicao) throws ExcecaoInstanciaNaoEncontrada{
		return despesaDao.buscarDespesa(connection, codEvento, nroEdicao, codDespesa);
	}
	public DespesaApresentador adicionaDespesaApresentador(DespesaApresentador despesaApresentador) throws ExcecaoNaoApresentador{
		Participante participante = null;
		try {
			participante = participanteDao.buscarParticipante(connection, 
					Long.valueOf(""+despesaApresentador.getNroInscricao()));
		} catch (NumberFormatException | ExcecaoInstanciaNaoEncontrada e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(participante.isTipoApresentador())
		return despesaApresentadorDao.adicionarDespesaApresentador(connection, despesaApresentador);
		else throw new ExcecaoNaoApresentador(participante.getNroInscricao());
	}
	public void removeDespesaApresentador (long codEvento, int nroEdicao, long codDespesa) throws ExcecaoInstanciaNaoEncontrada{
		despesaApresentadorDao.removerDespesaApresentador(connection, codEvento, nroEdicao, codDespesa);
	}
	public DespesaApresentador buscaDespesaApresentador (long codEvento, int nroEdicao, long codDespesa) 
			throws ExcecaoInstanciaNaoEncontrada{
		return despesaApresentadorDao.buscarDespesaApresentador(connection, codEvento, nroEdicao, codDespesa);
	}
	public List<DespesaApresentador> buscarDespesaApresentadorPorCodigo(Long codigoDespesa) {
		return despesaApresentadorDao.buscarDespesaPorCodigo(connection, codigoDespesa);
	}
	public List<DespesaApresentador> buscarDespesaApresentadorPorEventoEdicao(Long codEvento, Long nroEdicao) {
		return despesaApresentadorDao.buscarDespesaPorEventoEEdicao(connection, codEvento, nroEdicao);
	}
	
	
	public List<Despesa> buscarDespesaPorCodigo(Long codigoDespesa) throws ExcecaoInstanciaNaoEncontrada{
		return despesaDao.buscarDespesaPorCodigo(connection, codigoDespesa);
	}
	public List<Despesa> buscarDespesaPorEventoEEdicao(Long codEvento, Long nroEdicao) throws ExcecaoInstanciaNaoEncontrada{
		return despesaDao.buscarDespesaPorEventoEEdicao(connection, codEvento, nroEdicao);
	}
	
	public Edicao adicionaEdicao (Edicao edicao){
		return edicaoDao.adicionarEdicao(connection, edicao);
	}
	public void removeEdicao (long codEvento, int nroEdicao)
			throws ExcecaoInstanciaNaoEncontrada{
		edicaoDao.removerEdicao(connection, codEvento, nroEdicao);
	}
	public void updateEdicao (Edicao edicao)throws ExcecaoInstanciaNaoEncontrada{
		Edicao aux = edicaoDao.buscarEdicao(connection, edicao.getCodEvento(), edicao.getNroEdicao());
		edicao.setNroInscritosEdicao(aux.getNroInscritosEdicao());
		edicaoDao.updateEdicao(connection, edicao);
	}
	public Edicao buscaEdicao (long codEvento, int nroEdicao) throws ExcecaoInstanciaNaoEncontrada{
		return edicaoDao.buscarEdicao(connection, codEvento, nroEdicao);
	}
	public List<Edicao> buscaEdicoesPorEvento(Long codEvento){
		return edicaoDao.buscarEdicoesPorEvento(connection, codEvento);
	}
	public Evento adicionaEvento(Evento evento){
		return eventoDao.adicionarEvento(connection, evento);
	}
	public void removeEvento(long codEvento) throws ExcecaoInstanciaNaoEncontrada{
		eventoDao.removerEvento(connection, codEvento);
	}
	public void updateEvento (Evento evento) throws ExcecaoInstanciaNaoEncontrada{
		eventoDao.updateEvento(connection, evento);
	}
	public Evento buscaEvento (long codEvento) throws ExcecaoInstanciaNaoEncontrada{
		return eventoDao.buscarEvento(connection, codEvento);
	}
	public List<Evento> buscarTodosEventos(){
		return eventoDao.buscarTodosEventos(connection);
	}
        
	public Participante adicionaParticipante(Participante participante){
		Edicao edicao = null;
		try {
			edicao = edicaoDao.buscarEdicao(connection, participante.getCodEvento(), (int)participante.getNroEdicao());
		    edicao.setNroInscritosEdicao(edicao.getNroInscritosEdicao() + 1);
			edicaoDao.updateEdicao(connection, edicao);
		} catch (ExcecaoInstanciaNaoEncontrada e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return participanteDao.adicionarParticipante(connection, participante);
	}
	public void removeParticipante(long nroInscricao) throws ExcecaoInstanciaNaoEncontrada{
		Edicao edicao = null;
		Participante participante = participanteDao.buscarParticipante(connection, nroInscricao);
		try {
			edicao = edicaoDao.buscarEdicao(connection, participante.getCodEvento(), (int)participante.getNroEdicao());
		    edicao.setNroInscritosEdicao(edicao.getNroInscritosEdicao() - 1);
			edicaoDao.updateEdicao(connection, edicao);
		} catch (ExcecaoInstanciaNaoEncontrada e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		participanteDao.removerParticipante(connection, nroInscricao);
	}
	public void updateParticipante(Participante participante) throws ExcecaoInstanciaNaoEncontrada{
		participanteDao.updateParticipante(connection, participante);
	}
	public Participante buscaParticipante(long nroInscricao) throws ExcecaoInstanciaNaoEncontrada{
		return participanteDao.buscarParticipante(connection, nroInscricao);
	}
	public List<Long> buscarParticipantePorNome(String nomeParticipante) {
		return participanteDao.buscarParticipantePorNome(connection, nomeParticipante);
	}
	public List<Participante> buscarParticipantePorNroInscricao(Long nroIncricao) {
		return participanteDao.buscarParticipantePorNroInscricao(connection, nroIncricao);
	}
	
	public Patrocinador adicionaPatrocinador(Patrocinador patrocinador){
		return patrocinadorDao.adicionarPatrocinador(connection, patrocinador);
	}
	public void removePatrocinador(String cnpjPatrocinador) throws ExcecaoInstanciaNaoEncontrada{
		patrocinadorDao.removerPatrocinador(connection, cnpjPatrocinador);
	}
	public void updatePatrocinador(Patrocinador patrocinador) throws ExcecaoInstanciaNaoEncontrada{
		patrocinadorDao.updatePatrocinador(connection, patrocinador);
	}
	public Patrocinador buscaPatrocinador(String cnpjPatrocinador) throws ExcecaoInstanciaNaoEncontrada{
		return patrocinadorDao.buscarPatrocinador(connection, cnpjPatrocinador);
	}
	public List<Patrocinador> buscarTodosPatrocinadores() {
		return patrocinadorDao.buscarTodosPatrocinadores(connection);
	}
	
	public Patrocinio adicionaPatrocinio(Patrocinio patrocinio){
		return patrocinioDao.adicionarPatrocinio(connection, patrocinio);
	} 
	public void removePatrocinio(String cnpjPatrocinador,Long codEvento,Long nroEdicao) 
			throws ExcecaoInstanciaNaoEncontrada{
		patrocinioDao.removerPatrocinio(connection, cnpjPatrocinador, codEvento, nroEdicao);
	}
	public void updatePatrocinio(Patrocinio patrocinio) throws ExcecaoInstanciaNaoEncontrada, ExcecaoValorPatrocinioDiminuido{
		Patrocinio aux = patrocinioDao.buscarPatrocinio(connection, patrocinio.getCnpjPatrocinador(),
				patrocinio.getCodEvento(), patrocinio.getNroEdicao());
		if(patrocinio.getValorPatrocinio() >= aux.getValorPatrocinio()){
			patrocinio.setSaldoPatrocinio(patrocinio.getValorPatrocinio()-aux.getValorPatrocinio()
					+aux.getSaldoPatrocinio());
			patrocinioDao.updatePatrocinio(connection, patrocinio);
		}
		else throw new ExcecaoValorPatrocinioDiminuido(patrocinio.getCnpjPatrocinador(), 
				patrocinio.getCodEvento(), patrocinio.getNroEdicao());
	}
	public Patrocinio buscaPatrocinio(String cnpjPatrocinador,Long codEvento,Long nroEdicao)
			throws ExcecaoInstanciaNaoEncontrada{
		return patrocinioDao.buscarPatrocinio(connection, cnpjPatrocinador, codEvento, nroEdicao);
	}
	public List<Patrocinio> buscarPatrocinioPorCNPJ(String CNPJ) {
		return patrocinioDao.buscarPatrocinioPorCNPJ(connection, CNPJ);
	}
	public List<Patrocinio> buscarTodosPatrocinios() {
		return patrocinioDao.buscarTodosPatrocinios(connection);
	}
	public List<Patrocinio> buscarCNPJPatrocinioPorEDICAOeEVENTO(long codEvento, long nroEdicao) {
		return patrocinioDao.buscarCNPJPatrocinioPorEDICAOeEVENTO(connection, codEvento, nroEdicao);
	}

	public Pessoa adicionaPessoa(Pessoa pessoa){
		return pessoaDao.adicionarPessoa(connection, pessoa);
	}
	public void removePessoa(long codPessoa) throws ExcecaoInstanciaNaoEncontrada{
		pessoaDao.removerPessoa(connection, codPessoa);
	}
	public void updatePessoa(Pessoa pessoa) throws ExcecaoInstanciaNaoEncontrada{
		pessoaDao.updatePessoa(connection, pessoa);
	}
	public Pessoa buscaPessoa(long codPessoa) throws ExcecaoInstanciaNaoEncontrada{
		return pessoaDao.buscarPessoa(connection, codPessoa);
	}
	public List<Pessoa> buscarTodosEventos(long codigoPessoa) throws ExcecaoInstanciaNaoEncontrada{
		return pessoaDao.buscarTodosEventos(connection, codigoPessoa);
	}
}
